#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#       untitled.py
#       
#       Copyright 2010 Matteo Brusa <matteo@dell-desktop>
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.


import gobject
import cStringIO
import rhythmdb
import os
import gtk
import time
import cgi
import urllib
import mimetypes


from wsgiref.simple_server import WSGIRequestHandler
from wsgiref.simple_server import make_server
from LoggingWSGIRequestHandler import LoggingWSGIRequestHandler


def resolve_path(path):
    return os.path.join(os.path.dirname(__file__), path)
    
    
def parse_post(environ):
    if 'CONTENT_TYPE' in environ:
        length = -1
        if 'CONTENT_LENGTH' in environ:
            length = int(environ['CONTENT_LENGTH'])
        if environ['CONTENT_TYPE'] == 'application/x-www-form-urlencoded':
            return cgi.parse_qs(environ['wsgi.input'].read(length))
        if environ['CONTENT_TYPE'] == 'multipart/form-data':
            return cgi.parse_multipart(environ['wsgi.input'].read(length))
    return None

def return_redirect(path, environ, response):
    if not path.startswith('/'):
        path_prefix = environ['REQUEST_URI']
        if path_prefix.endswith('/'):
            path = path_prefix + path
        else:
            path = path_prefix.rsplit('/', 1)[0] + path
    scheme = environ['wsgi.url_scheme']
    if 'HTTP_HOST' in environ:
        authority = environ['HTTP_HOST']
    else:
        authority = environ['SERVER_NAME']
    port = environ['SERVER_PORT']
    if ((scheme == 'http' and port != '80') or
        (scheme == 'https' and port != '443')):
        authority = '%s:%s' % (authority, port)
    location = '%s://%s%s' % (scheme, authority, path)
    status = '303 See Other'
    response_headers = [('Content-Type', 'text/plain'),
                        ('Location', location)]
    response(status, response_headers)
    return [ 'Redirecting...' ]



class RhythmboxGWTServer(object):

    def __init__(self, hostname, port, plugin):
        self.plugin = plugin
        self.running = True
        self.artist = None
        self.album = None
        self.title = None
        self.stream = None
        self._httpd = make_server(hostname, port, self._wsgi,
                                  handler_class=LoggingWSGIRequestHandler)
        self._watch_cb_id = gobject.io_add_watch(self._httpd.socket,
                                                 gobject.IO_IN,
                                                 self._idle_cb)
                                                 
       
        

    def shutdown(self):
# this hangs        
#        self._httpd.shutdown()
        gobject.source_remove(self._watch_cb_id)
        self.running = False
        self.plugin = None
        

    def set_playing(self, artist, album, title, stream):
        self.artist = artist
        self.album = album
        self.title = title
        self.stream = stream

    def _open(self, filename):
        filename = os.path.join(os.path.dirname(__file__), filename)
        return open(filename)

    def _idle_cb(self, source, cb_condition):
        if not self.running:
            return False
        self._httpd.handle_request()
        return True

    def _wsgi(self, environ, response):
        path = environ['PATH_INFO']
        if path.startswith("/query"):
            return self._handle_query(environ, response)
        elif path.startswith("/player"):
            return self._handle_player(environ, response)   
        elif path.startswith("/cover"):
            return self._handle_cover(environ, response)
        else:
            return self._handle_static(environ, response)
            
            
    def _clear_q(self, shell):
        source = shell.props.queue_source
        model = source.get_property("query-model")
        for row in iter(model):
            model.remove_entry(row[0])
            

    def _get_field(self, db, entry, field):
        res=  res= db.entry_get(entry, field)
        return res.replace(";", " ")
        
    def _get_status(self, db, query_model):
        res=""      
        
        # playlist and current track
        current= self.plugin.shell.props.shell_player.get_playing_entry()
        
        n= 0
        index= -1
        for row in query_model:
            entry = row[0]
            res+= str(db.entry_get(entry, rhythmdb.PROP_TRACK_NUMBER))
            res+= ";"
            res+= self._get_field(db, entry, rhythmdb.PROP_TITLE)
            res+= ";"
            res+= self._get_field(db, entry, rhythmdb.PROP_ALBUM)
            res+= ";"
            res+= self._get_field(db, entry, rhythmdb.PROP_ARTIST)
            res+="\n"
            if current==entry:
                index=n
            n=n+1
            
        print "current index: " +str(index)
            
        # local album art
        url= "no cover"
        if not current is None:
            ur= self._get_cover()
            if (ur != None):
                url= ur
            
        return url + "\n" + str(index) + "\n" + res
        
    def _get_cover(self):
        current= self.plugin.shell.props.shell_player.get_playing_entry()
        db = self.plugin.db
        path= db.entry_get(current, rhythmdb.PROP_LOCATION)
        path= path.rpartition("/")
        print "path: " + path[0]
        # search for jpg in this path
        return None
        
        
    def _parse_params(self, s):
        dict={}        
        lst= s.split("&")
        print s+" len "+ str(len(lst))
        if len(s)>0:
			for keyvalue in lst:
				pair= keyvalue.split("=")
				dict.update({urllib.unquote(pair[0]):urllib.unquote(pair[1])})
        return dict
            
    def _handle_query(self, environ, response):
        scanner= self.plugin.scanner

        response('200 OK', [('Content-type','text/plain; charset=UTF-8')])
        res=""
        list=[]
            
        query = environ['QUERY_STRING']
        params= self._parse_params(query)
        type= params.get("type")
         
        if type=="album":
            artist_id= params.get("artist")
            artist=None
            if artist_id!=None:
                artist= scanner.artists[int(artist_id)]

            n=0;
            for album in scanner.albums:
                if artist==None or album[1]==artist:
                    list.append (str(n)+";"+album[0].replace(";"," ")+";"+album[1].replace(";"," ")+"\n")
                n= n+1

        elif type=="artist":
            n=0;
            for artist in scanner.artists:
                list.append (str(n)+";"+artist.replace(";"," ")+"\n")
                n= n+1

        return "".join(list)

    def _handle_player(self, environ, response):
        
        shell = self.plugin.shell
        player = self.plugin.player
        scanner= self.plugin.scanner
        query_model = shell.props.queue_source.props.query_model
        queue = shell.props.queue_source
        db = self.plugin.db
        
        response('200 OK', [('Content-type','text/plain; charset=UTF-8')])
        res=""
        
        query = environ['QUERY_STRING']
        params= self._parse_params(query)
        
        action= params.get("action")
        print "action: "+ action
        if "playAlbum"==action:
            self._clear_q(shell)
            playlist= scanner.get_album_playlist(params.get("id"))
            for item in playlist:
                self.plugin.shell.add_to_queue(item)
            print("start play")
            player.play_entry(iter(query_model).next()[0], queue)
        elif "stop"==action:
            player.stop()
        elif "next"==action:
            player.do_next()
        elif "previous"==action:
            player.do_previous()
        elif "jump"==action:
            current= player.get_playing_entry()
            index= params.get("index")
            print "current: " + str(current) + " index: " + index
            
            iterator= iter(query_model)
            for x in xrange(int(index)):
                item= iterator.next()
            print item[0]
            player.play_entry(item[0], queue)
        elif "volUp"==action :
            player.set_volume(player.get_volume() + 0.1)
        elif "volDown"==action :
            player.set_volume(player.get_volume() - 0.1)
        elif "getStatus"==action :
            res= self._get_status(db,query_model)   
        elif "playRandomAlbum"==action:
            self._clear_q(shell)
            playlist= scanner.get_random_album_playlist()
            for item in playlist:
                self.plugin.shell.add_to_queue(item)
            print("start random play")
            player.play_entry(iter(query_model).next()[0], queue)
        return res 
 

    def _handle_static(self, environ, response):
        rpath = environ['PATH_INFO']

        path = rpath.replace('/', os.sep)
        path = os.path.normpath(path)
        if path[0] == os.sep:
            path = path[1:]
        if path=="":
            path="index.html"
        path = resolve_path("htdocs/"+path)

        if os.path.isfile(path):
            lastmod = time.gmtime(os.path.getmtime(path))
            lastmod = time.strftime("%a, %d %b %Y %H:%M:%S +0000", lastmod)
            mimetype = mimetypes.guess_type(path)[0]
            response_headers = [('Content-type',mimetype),
                                ('Last-Modified', lastmod)]
            response('200 OK', response_headers)
            return open(path)
        else:
            response_headers = [('Content-type','text/plain')]
            response('404 Not Found', response_headers)
            return 'File not found: %s\n' % rpath 

    def _handle_cover(self, environ, response):
      
        path= _get_cover()
        if (path==None):
            return
        
        print "cover: " + path
        
        path = os.path.normpath(path)
        if path[0] == os.sep:
            path = path[1:]
        if path=="":
            path="index.html"
        path = resolve_path("htdocs/"+path)

        if os.path.isfile(path):
            lastmod = time.gmtime(os.path.getmtime(path))
            lastmod = time.strftime("%a, %d %b %Y %H:%M:%S +0000", lastmod)
            mimetype = mimetypes.guess_type(path)[0]
            response_headers = [('Content-type',mimetype),
                                ('Last-Modified', lastmod)]
            response('200 OK', response_headers)
            return open(path)
        else:
            response_headers = [('Content-type','text/plain')]
            response('404 Not Found', response_headers)
            return 'File not found: %s\n' % rpath 

